package com.cetccloud.ap.proxy.channel.cossDomain.s30;

import com.alibaba.fastjson.JSON;
import com.cetccloud.ap.config.ProxyConfig;
import com.cetccloud.ap.proxy.channel.cossDomain.s30.channel.recv.S30RecvChannel;
import com.cetccloud.ap.proxy.channel.cossDomain.s30.channel.send.S30SendChannel;
import com.cetccloud.ap.proxy.channel.cossDomain.s30.handler.send.MessageHandler;
import com.cetccloud.ap.proxy.channel.cossDomain.s30.handler.send.MetaReqHandler;
import com.cetccloud.ap.proxy.channel.cossDomain.s30.handler.send.RegisterReqHandler;
import com.cetccloud.ap.proxy.channel.cossDomain.s30.handler.send.file.FileXmlHandler;
import com.thunisoft.exchange.gateway.protocol.entity.GatewayExchangeNode;
import com.thunisoft.exchange.gateway.protocol.entity.RegisterExchangeNode;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * @ClassName S30Adapter
 * @Description
 * @Author superz
 * @Date 2021/4/22 20:26
 * @Version 1.0
 **/
@Slf4j
@Component
public class S30Adapter {

    public static final String SEND_CONNECTED_EVENT = "send_connected_event";

    public static final String RECV_CONNECTED_EVENT = "recv_connected_event";

    public static final String REGISTER_EVENT = "register_event";

    @Autowired
    private Vertx vertx;

    @Autowired
    @Getter
    private S30Config s30Config;

    @Autowired
    private ProxyConfig proxyConfig;

    @Autowired
    private S30SendChannel s30SendChannel;

    @Autowired
    private S30RecvChannel s30RecvChannel;

    @Autowired
    private MessageHandler messageHandler;

    @Autowired
    private FileXmlHandler fileXmlHandler;

    @Autowired
    private RegisterReqHandler registerReqHandler;

    @Autowired
    private MetaReqHandler metaReqHandler;

    @PostConstruct
    private void start() {
        if (proxyConfig.isMock()) {
            log.info("### S30Adapter init [mock state] ###");
            return;
        }

        Future sendFuture = Future.future(event -> {
            vertx.eventBus().<String>consumer(SEND_CONNECTED_EVENT, message -> {
                if (!Boolean.parseBoolean(message.body())) {
                    log.error("s30发送端连接失败");
                    event.fail("s30发送端连接失败");
                }
                event.tryComplete();
            });
        });

        Future recvFuture = Future.future(event -> {
            vertx.eventBus().<String>consumer(RECV_CONNECTED_EVENT, message -> {
                if (!Boolean.parseBoolean(message
                        .body())) {
                    log.error("s30接收端端连接失败");
                    event.fail("s30接收端端连接失败");
                }
                event.tryComplete();
            });
        });

        CompositeFuture.all(sendFuture, recvFuture).onSuccess(f -> {
            try {
                // 手工注册
                if (BooleanUtils.isFalse(s30Config.getProxy().getAutoRegister())) {
                    log.info("### S30Adapter start [手动注册] ###");
                    // 主动请求名录数据
                    metaReq();
                    return;
                }
                registerReq();
            } catch (S30Exception e) {
                log.error("S30Adapter start error", e);
                log.error("主动请求名录数据失败 or 自动注册失败，系统退出...");
                System.exit(1);
            }
        }).onFailure(t -> {
            log.error("s30发送端 or 接收端连接失败，系统退出...");
            System.exit(1);
        });

        vertx.eventBus().<String>consumer(REGISTER_EVENT, message -> {
            try {
                // 更新配置信息
                RegisterExchangeNode selfNode = JSON.parseObject(message.body(), RegisterExchangeNode.class);
                s30Config.getProxy().setZoneId(selfNode.getZone_id());
                s30Config.getProxy().setAppId(selfNode.getApp().getApp_id());

                // 自动注册成功后，去获取名录信息
                metaReq();
            } catch (S30Exception e) {
                log.error("S30Adapter start error", e);
                log.error("主动请求名录数据失败，系统退出...");
                System.exit(1);
            }
        });

        // 启动s30 channel
        s30SendChannel.start();
        s30RecvChannel.start();
    }

    /**
     * 4.2.2.2 自动注册
     **/
    private void registerReq() throws S30Exception {
        registerReqHandler.handle();
    }

    /**
     * 4.4.2 应用程序主动请求名录数据
     **/
    private void metaReq() throws S30Exception {
        metaReqHandler.handle();
    }

    /**
     * 消息传输
     **/
    public String message(String destAppId, String data) throws S30Exception {
        List<String> msgIdList = messageHandler.handle(Arrays.asList(destAppId), data);
        if (CollectionUtils.isNotEmpty(msgIdList)) {
            return msgIdList.get(0);
        }
        return StringUtils.EMPTY;
    }

    /**
     * 消息传输
     **/
    public List<String> message(List<String> destAppIds, String data) throws S30Exception {
        return messageHandler.handle(destAppIds, data);
    }

    /**
     * 文件xml传输
     **/
    public String fileXml(String destAppId, String fileUrl, long fileSize) throws S30Exception {
        List<String> msgIdList = fileXmlHandler.handle(Arrays.asList(destAppId), fileUrl, fileSize);
        if (CollectionUtils.isNotEmpty(msgIdList)) {
            return msgIdList.get(0);
        }
        return StringUtils.EMPTY;
    }

    /**
     * 文件xml传输
     **/
    public List<String> fileXml(List<String> destAppIds, String fileUrl, long fileSize) throws S30Exception {
        return fileXmlHandler.handle(destAppIds, fileUrl, fileSize);
    }

    public String getProxyAppId(String zoneId) {
        if ("608d01c32849463b2fcf9913".equals(zoneId)) {
            return "ds-a-30-test";
        }
        if ("hy_b".equals(zoneId)) {
            return "ds-b-754-test";
        }
        return s30RecvChannel.getProxyZoneAppMap().get(zoneId);
    }

    /**
     * 获取可见域名录信息
     **/
    public Collection<GatewayExchangeNode> getProxyMeta() {
        return s30RecvChannel.getExchangeNodes();
    }

    @PreDestroy
    private void stop() {
        s30SendChannel.stop();
        s30RecvChannel.stop();
    }
}
